/*
 * This file is Copyright 2002-2006 Loyola University Chicago,
 * Department of Computer Science and the Emerging Technologies Laboratory.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License via
 *    http://www.apache.org/licenses/LICENSE-2.0.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.citep.web.gwt.widgets;

import java.util.ArrayList;
import com.citep.web.gwt.cache.AccountTreeCache;
import com.citep.web.gwt.cache.AccountTreeListener;
import com.citep.web.gwt.dto.*;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.FocusListener;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.Window;

public class EditableAccountPanel extends Composite implements AccountTreeListener, KeyboardListener, SuggestionListener,EditableWidget {


	private AccountTreeCache cache;
	
	private final HorizontalPanel panel = new HorizontalPanel();
	private Label inactiveLabel;
	private TextBox editBox;
	private String initialLabelText;
	private String previousText = "";
	private EditableWidgetListener listener;
	
	private static AccountAutoSuggest suggester;
	
	public void initializeSuggestions() {
		getSuggester().clearSuggestions();
		cache.getAccountTree(this);
	}
	
	private static AccountAutoSuggest getSuggester() {
		if(suggester == null) {
			suggester = new AccountAutoSuggest(10);
			suggester.setVisible(false);
		}
		return suggester;
	}

	public void initialize(String value) {
		inactiveLabel.setText(value);
		showEditBox();
	}
	
	public void setEditableWidgetListener(EditableWidgetListener l) {
		listener = l;
	}
	
	public EditableAccountPanel(String labelText, String labelStyle, String editBoxStyle, String tableStyle, String highLightStyle) {
		cache = AccountTreeCache.getCache();
		this.initWidget(panel);
		
		getSuggester().setTableStyle(tableStyle);
		getSuggester().setHighlightStyle(highLightStyle);
		
		initialLabelText = labelText;
		
		inactiveLabel = new Label(initialLabelText);
		inactiveLabel.setText(labelText);
		inactiveLabel.setStyleName(labelStyle);
		inactiveLabel.addClickListener(new ClickListener() {
			
			public void onClick(Widget sender) {
				showEditBox();
			}
		});
		
		
		editBox = new TextBox();
		editBox.setStyleName(editBoxStyle);
		editBox.addFocusListener(new FocusListener() {
			public void onFocus(Widget sender) {
				
			}

			public void onLostFocus(Widget sender) {
				commitEdit();
			}
		});
		
		editBox.addKeyboardListener(this);
		
		//editBox.addKeyboardListener(listener)
		panel.add(inactiveLabel);
	}
	
	private void showEditBox() {
		if(panel.getWidget(0) != editBox) {
			initializeSuggestions();
			previousText = inactiveLabel.getText();
			panel.remove(0);
			panel.add(editBox);
			editBox.setFocus(true);
		} else {
			editBox.setFocus(true);
		}
	}
	
	private void showLabel(String text) {
		if(panel.getWidget(0) != inactiveLabel) {
			panel.remove(0);
			panel.add(inactiveLabel);
		}
		inactiveLabel.setText(text);
	}
	
	private boolean validateBox() {
		return editBox.getText().length() > 0;
	}

	private void commitEdit() {
		if(validateBox()) {
			if(listener != null)
				listener.onEditComplete(editBox.getText());

			showLabel(editBox.getText());
		} else {
			
			Window.alert("Invalid account name");
			editBox.setFocus(true);
		}
	}
	
	private void rollBackEdit() {
		showLabel(previousText);
	}
	
	
	public AccountDTO getSelectedAccount() {
		return null;
	}

	public void onAccountTreeCurrent() { }

	public void onAccountTreeLoadFailure(Throwable t) { }

	public void addAccountToSuggestions(AccountTreeNode node, String parentName) {

		//"fully qualified account name, so that there are no collitions between
		//accounts who have the same name in different parent nodes
		String fqan = "";
		
		if(parentName != null && parentName.length() > 0) {
			fqan = parentName + " : " + node.getAccount().getName();
		} else {
			fqan = node.getAccount().getName();
		}
		
		getSuggester().addSuggestion(fqan);
		
		ArrayList children = node.getChildren();
		if(children != null) {
			for(int i = 0; i < children.size(); i++) {
				addAccountToSuggestions((AccountTreeNode)children.get(i), fqan);
			}
		}		
	}
	
	public void onAccountTreeReady(AccountTreeNode root) {
		ArrayList children = root.getChildren();
		if(children != null) {
			for(int i = 0; i < children.size(); i++) {
				addAccountToSuggestions((AccountTreeNode)children.get(i),"");
			}
		}
	}

	public void onKeyDown(Widget sender, char keyCode, int modifiers) {
		// TODO Auto-generated method stub
		
	}

	public void processInput() {
		if(!getSuggester().isVisible()) {
			
			int suggestOffsetWidth = 250; //idaelly use getSuggester().getOffsetWidth(), but since it's not on screen it returns 0
			
			int yCoord = editBox.getAbsoluteTop() + editBox.getOffsetHeight();
			int right = editBox.getAbsoluteLeft() + suggestOffsetWidth;
			
			int xCoord;
			if(Window.getClientWidth() < right)
				xCoord = editBox.getAbsoluteLeft() + editBox.getOffsetWidth() - suggestOffsetWidth;
			else
				xCoord = editBox.getAbsoluteLeft();
			
			getSuggester().setPopupPosition(xCoord, yCoord);
			
			getSuggester().setSuggestionListener(this);
			getSuggester().setVisible(true);
			getSuggester().show();
			System.out.println("init suggester");
			
		}
		
		System.out.println("sending: " + editBox.getText());
		getSuggester().textChanged(editBox.getText());
	}
	
	public void onKeyPress(Widget sender, char keyCode, int modifiers) {
	}

	public void onKeyUp(Widget sender, char keyCode, int modifiers) {
		// TODO Auto-generated method stub
		switch(keyCode) {
			case KEY_ENTER:
				String suggestion = getSuggester().getCurrentSuggestion();
				onSuggestionClicked(suggestion);
			case KEY_DOWN:
				getSuggester().scrollDown();
				break;
			case KEY_UP:
				getSuggester().scrollUp();
				break;
			case KEY_ESCAPE:
				getSuggester().hide();
				rollBackEdit();
				break;
			default:
				processInput();
				break;
		}	
	}

	public void onSuggestionChanged(String suggestion) {
		// TODO Auto-generated method stub
		
	}
	
	public void onSuggestionClicked(String suggestion) {
		//the user has clicked on one of the suggestions
		editBox.setText(suggestion);
		commitEdit();
		getSuggester().setVisible(false);
		getSuggester().hide();
	}
}
